package com.jinke.api.modules.third.dqpost.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.jinke.api.common.api.CommonResult;
import com.jinke.api.common.util.CommonUtil;
import com.jinke.api.common.util.Global;
import com.jinke.api.modules.app.enums.BalanceLogType;
import com.jinke.api.modules.app.enums.OrderStatus;
import com.jinke.api.modules.app.enums.OrderType;
import com.jinke.api.modules.app.enums.ValidateStatus;
import com.jinke.api.modules.app.model.Order;
import com.jinke.api.modules.app.model.OrderParcel;
import com.jinke.api.modules.app.response.CreateLabel2Response;
import com.jinke.api.modules.app.service.IUserOrderTaskService;
import com.jinke.api.modules.app.service.OrderParcelService;
import com.jinke.api.modules.app.service.OrderService;
import com.jinke.api.modules.app.service.UserRechargeService;
import com.jinke.api.modules.app.util.MathUtil;
import com.jinke.api.modules.app.util.OssUtil;
import com.jinke.api.modules.base.service.ThirdService;
import com.jinke.api.modules.third.dqpost.model.request.GetLabelsRequest;
import com.jinke.api.modules.third.dqpost.model.response.DQOrderResponse;
import com.jinke.api.modules.third.dqpost.model.response.GetLabelResponse;
import com.jinke.api.modules.third.dqpost.model.response.GetPriceResponse;
import com.jinke.api.modules.third.dqpost.service.DqpostService;
import com.jinke.api.modules.third.dqpost.util.DqpostlUtil;
import com.jinke.api.modules.third.ezeeship.model.request.EstimateRateRequest;
import com.jinke.api.modules.third.ezeeship.model.response.CreateLabelResponse;
import com.jinke.api.modules.third.ezeeship.model.response.EstimateRateResponse;
import com.jinke.api.modules.third.ezeeship.util.EzeeShipUtil;
import com.jinke.api.modules.third.sjgj.model.response.CreateOrderResponse;
import com.jinke.api.modules.third.sjgj.util.SjgjwlUtil;
import com.jinke.api.modules.ums.model.Channel;
import com.jinke.api.modules.ums.model.UmsAdmin;
import com.jinke.api.modules.ums.service.ChannelService;
import com.jinke.api.modules.ums.service.UmsAdminService;
import com.jinke.api.modules.ums.vo.UserChannelVO;
import com.jinke.api.security.util.ApiUserUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author macro
 * @since 2024-01-13
 */
@Service
@Slf4j
public class DqpostServiceImpl implements DqpostService {
    public static final String DQPOST_COM = "https://api.dqpost.com";
    @Resource
    private UmsAdminService umsAdminService;
    @Resource
    private ChannelService channelService;
    @Resource
    private OssUtil ossUtil;
    @Resource
    private SjgjwlUtil sjgjwlUtil;
    @Resource
    private OrderService orderService;

    @Resource
    private OrderParcelService orderParcelService;

    @Resource
    private UserRechargeService userRechargeService;
    @Resource
    private ThirdService thirdService;
    @Resource
    private DqpostlUtil dqpostlUtil;
    @Resource
    private EzeeShipUtil ezeeShipUtil;
    @Resource
    private IUserOrderTaskService iUserOrderTaskService;

    @Override
    public CommonResult estimateRate(EstimateRateRequest request) {
        Integer userId = ApiUserUtil.getUserId();
        return estimateRate(request, userId);
    }

    @Override
    public CommonResult estimateRate(EstimateRateRequest request, Integer userId) {
        UserChannelVO userChannelVO = request.getUserChannelVO();
        Channel channel = userChannelVO.getChannel();
        request.setServiceCode(channel.getChannelCode());
        BigDecimal rateAmount;
        try {
            rateAmount = getPriceAmount(request, userId, userChannelVO);
        } catch (Exception e) {
            return CommonResult.failed(e.getMessage());
        }
        if (rateAmount.compareTo(new BigDecimal("0")) == 0) {
            return CommonResult.failed("系统异常请联系管理员");
        }
        EstimateRateResponse.Data newData = new EstimateRateResponse.Data();
        newData.setRate(rateAmount);
        return CommonResult.success(newData);
    }

    private BigDecimal getPriceAmount(EstimateRateRequest request, Integer userId, UserChannelVO vo) {
        BigDecimal rateAmount = new BigDecimal("0");
        String strResult =   dqpostlUtil.getPrice(request);
        if (StringUtils.isNotEmpty(strResult)) {
            GetPriceResponse getPriceResponse = JSONUtil.toBean(strResult, GetPriceResponse.class);
            if (!getPriceResponse.isSuccess()) {
                throw new RuntimeException(getPriceResponse.getMsg());
            }
            GetPriceResponse.GetPriceResponseDetail data = getPriceResponse.getData();
            BigDecimal price = data.getPrice();
            rateAmount = thirdService.calcRate(userId, vo, price);
        }
        return rateAmount;
    }

    @Override
    public CommonResult createLabel(EstimateRateRequest request) {
        Integer userId = ApiUserUtil.getUserId();

        return createLabel(request, userId);
    }

    @Override
    public CommonResult createLabel(EstimateRateRequest request, Integer userId) {
        Integer channelId = request.getChannelId();
        UserChannelVO userChannelVO = request.getUserChannelVO();
        //估价
        BigDecimal rateAmount;
        try {
            rateAmount = getPriceAmount(request, userId, userChannelVO);
        } catch (Exception e) {
            return CommonResult.failed(e.getMessage());
        }
        UmsAdmin umsAdmin = umsAdminService.getById(userId);
        if (rateAmount.compareTo(new BigDecimal("0")) == 0 || ObjectUtils.isEmpty(umsAdmin)) {
            return CommonResult.failed("数据异常");
        }
        //计算当前用户的可支配金额
        BigDecimal totalAmount = umsAdmin.getBalance().add(umsAdmin.getCreditBalance());
        if (totalAmount.compareTo(rateAmount) < 0) {
            return CommonResult.failed("Insufficient Balance");
        }
        if (StringUtils.isBlank(request.getOrderNO())) {
            request.setOrderNO(CommonUtil.getOrderNo());
        }
        Channel channel = channelService.getOne(new LambdaQueryWrapper<Channel>().eq(Channel::getId, channelId));
        request.setServiceCode(channel.getChannelCode());
        String strResult =   dqpostlUtil.createOrder(request);
        if (StringUtils.isNotEmpty(strResult)) {
            DQOrderResponse dqOrderResponse;
            try {
                dqOrderResponse = JSON.parseObject(strResult, DQOrderResponse.class);
            } catch (Exception e) {
                // 解析JSON
                JSONObject jsonObject = new JSONObject(strResult);
                String message = jsonObject.get("msg").toString();
                log.info("============dpPost下单解析失败==============={}", strResult);
                return CommonResult.failed(message);
            }
            Order order = new Order();
            BeanUtils.copyProperties(request, order);
            order.setId(request.getOrderId());
            if (dqOrderResponse.toCommonResult().isSucess()) {
                order.setUserId(userId);
                order.setOrderNo(request.getOrderNO());
                DQOrderResponse.GetPriceResponseDetail data = dqOrderResponse.getData();
                BigDecimal price = data.getPrice();
                BigDecimal afterRate = thirdService.calcRate(userId, userChannelVO, price);
                order.setRate(afterRate);
                order.setOriginFee(price);

                GetLabelsRequest getLabelsRequest = new GetLabelsRequest();
                String platformNo = data.getPlatformNo();
                getLabelsRequest.setPlatformNo(platformNo);

                String newPdfUrl = "";
                String objectId = "";
                String trackingNo = "";
                List<String> trackingNos = new ArrayList<>();

                // 同步更新订单号
                int t = 0;
                String errStr = "";
                while (t++ < 15) {

                    String labelStr =   dqpostlUtil.getLabels(getLabelsRequest);
                    if (StringUtils.isNotEmpty(labelStr)) {
                        GetLabelResponse getLabelResponse = JSON.parseObject(labelStr, GetLabelResponse.class);
                        if (getLabelResponse.isSuccess()) {
                            errStr = "";
                            GetLabelResponse.GetPriceResponseDetail getPriceResponseDetail = getLabelResponse.getData();
                            String pdfUrl = DQPOST_COM + getPriceResponseDetail.getLabelUrl();
                            trackingNo = getPriceResponseDetail.getTrackingNo();
                            trackingNos = getPriceResponseDetail.getTrackingNos();
                            // 上传到oss
                            objectId = platformNo;
                            ossUtil.upload("pdf", objectId + ".pdf", pdfUrl);

                            newPdfUrl = Global.PRINT_LABEL_API + objectId;
                            order.setPdfUrl(newPdfUrl);
                            order.setObjectId(objectId);
                            break;
                        } else {
                            errStr = getLabelResponse.getMsg();
                            if ("订单创建中".equals(errStr)) {
                                try {
                                    Thread.sleep(2000L);
                                } catch (InterruptedException e) {
                                    throw new RuntimeException(e);
                                }
                            } else {
                                break;
                            }
                        }
                    }
                }


                // 失败
                if (StringUtils.isNotBlank(errStr)) {
                    errStr = ezeeShipUtil.fmtMsg(errStr);
                    if (order.getId() != null) {
                        orderService.update(new LambdaUpdateWrapper<Order>().eq(Order::getId, order.getId()).set(Order::getErrMsg, errStr));
                    }
                    return CommonResult.failed(errStr);
                }
                // 扣钱
                BigDecimal finalRate = afterRate;
                if (finalRate != null && BigDecimal.ZERO.compareTo(finalRate) < 0) {
                    // change 使用扣钱失败当场取消
                    userRechargeService.decrTransfer(userId, finalRate, BalanceLogType.CONSUME, "寄件", order.getOrderNo(), order.getObjectId(), channel,null);
                }


                //下单成功之后将用户销售id增加进去
                if (ObjectUtils.isNotEmpty(umsAdmin.getSellerId())) {
                    order.setSellerId(umsAdmin.getSellerId());
                }
                //设置错误信息为空
                order.setErrMsg("");
                // order.setCreateTime(LocalDateTime.now());
                order.setFromCity(request.getFrom().getCity());
                order.setFromEmail(request.getFrom().getEmail());
                order.setFromCompany(request.getFrom().getCompany());
                order.setFromPhone(request.getFrom().getPhone());
                order.setFromAddressLine2(request.getFrom().getAddressLine2());
                order.setFromAddressLine1(request.getFrom().getAddressLine1());
                order.setFromCountryCode(request.getFrom().getCountryCode());
                order.setFromZipCode(request.getFrom().getZipCode());
                order.setFromPersonName(request.getFrom().getPersonName());
                order.setFromStateCode(request.getFrom().getStateCode());

                try {
                    order.setReference(request.getExtra().getReference());
                    order.setReference2(request.getExtra().getReference2());
                }catch (Exception e){
                    log.error("设置reference出错了");
                }


                EstimateRateRequest.Address requestTo = request.getTo();
                order.setToCity(requestTo.getCity());
                order.setToEmail(requestTo.getEmail());
                order.setToCompany(requestTo.getCompany());
                order.setToPhone(requestTo.getPhone());
                order.setToAddressLine2(requestTo.getAddressLine2());
                order.setToAddressLine1(requestTo.getAddressLine1());
                order.setToCountryCode(requestTo.getCountryCode());
                order.setToZipCode(requestTo.getZipCode());
                order.setToPersonName(requestTo.getPersonName());
                order.setToStateCode(requestTo.getStateCode());
                order.setOrderType(OrderType.API);

                order.setStatus(OrderStatus.RECENT.getValue());

                order.setCreateTime(LocalDateTime.now());
                if (BooleanUtil.isTrue(requestTo.getIsValid())) {
                    order.setValidateStatus(ValidateStatus.defaultEnum(requestTo.getIsResidential()));
                } else {
                    order.setValidateStatus(ValidateStatus.UN_VALIDATE);
                }
                // 保证金
                BigDecimal earnestRate = umsAdmin.getEarnestRate();
                BigDecimal subEarnestBalance = MathUtil.formatBigDecimal(afterRate.multiply(earnestRate));
                order.setEarnest(subEarnestBalance);

                orderService.saveOrUpdate(order);
                //定时任务表插入一条数据
                iUserOrderTaskService.saveByOrderId(order.getId());

                Integer orderId = order.getId();
                //更新包裹信息
                updateParcel(request, userId, newPdfUrl, trackingNos, orderId);



                CreateLabelResponse.Data newCreateLabelResponseData = new CreateLabelResponse.Data();
                newCreateLabelResponseData.setRate(finalRate);

                CreateLabel2Response.FeeDetail newFeeDetail = new CreateLabel2Response.FeeDetail();
                newFeeDetail.setBaseRate(finalRate);
                newCreateLabelResponseData.setFeeDetail(newFeeDetail);

                newCreateLabelResponseData.setRate(finalRate);
                newCreateLabelResponseData.setStatus(1);
                newCreateLabelResponseData.setCreateTime(LocalDateTime.now());
                newCreateLabelResponseData.setObjectId(objectId);
                newCreateLabelResponseData.setPdfUrl(newPdfUrl);
                newCreateLabelResponseData.setTrackingNumber(Arrays.asList(trackingNo));
                String labelUrl = Global.PRINT_LABEL_API + objectId;
                newCreateLabelResponseData.setLabelUrl(Arrays.asList(labelUrl));

                return CommonResult.success(newCreateLabelResponseData);
            } else {
                if (order.getId() != null) {
                    orderService.update(new LambdaUpdateWrapper<Order>().eq(Order::getId, order.getId()).set(Order::getErrMsg, dqOrderResponse.toCommonResult().getMessage()));
                }
                return CommonResult.failed(dqOrderResponse.toCommonResult().getMessage().replaceAll("接口返回：：", ""));
            }
        }
        return CommonResult.success();
    }

    /**
     * 更新包裹信息
     * @param request
     * @param userId
     * @param newPdfUrl
     * @param trackingNos
     * @param orderId
     */
    @Transactional
      void updateParcel(EstimateRateRequest request, Integer userId, String newPdfUrl, List<String> trackingNos, Integer orderId) {
        List<EstimateRateRequest.Parcel> parcels = request.getParcels();
        List<OrderParcel> orderParcels = parcels.stream().map(x -> {
            OrderParcel orderParcel = new OrderParcel();
            orderParcel.setOrderId(orderId);
            orderParcel.setUserId(userId);
            BeanUtils.copyProperties(x, orderParcel);
            EstimateRateRequest.Extra extra = x.getExtra();
            if (extra != null) {
                BeanUtils.copyProperties(extra, orderParcel);
            }

            return orderParcel;
        }).collect(Collectors.toList());

        // 入库
        orderParcelService.remove(new LambdaQueryWrapper<OrderParcel>().eq(OrderParcel::getOrderId, orderId));
        for (int i = 0; i < orderParcels.size(); i++) {
            if (trackingNos.size() > i) {
                orderParcels.get(i).setTrackingNumber(trackingNos.get(i).replaceAll("\\[\"", "").replaceAll("\"\\]", ""));
            } else {
                orderParcels.get(i).setTrackingNumber(trackingNos.get(0).replaceAll("\\[\"", "").replaceAll("\"\\]", ""));
            }
            orderParcels.get(i).setLabelUrl(newPdfUrl);
        }
        orderParcelService.saveBatch(orderParcels);
    }



    @Override
    public CommonResult getLabel(String objectId) {

        return getLabel(objectId, null);

    }

    @Override
    public CommonResult getLabel(String objectId, Integer userId) {
        log.info(JSONUtil.toJsonStr(objectId));
        GetLabelsRequest getLabelsRequest = new GetLabelsRequest();
        getLabelsRequest.setPlatformNo(objectId);
        CreateLabelResponse.Data createLabelResponseData = new CreateLabelResponse.Data();

        if (userId == null) {
            userId = ApiUserUtil.getUserId();
        }
        Order order = orderService.getOne(new LambdaQueryWrapper<Order>()
                .eq(Order::getObjectId, objectId)
                .eq(Order::getUserId, userId)
        );

        if (order == null) {
            return CommonResult.success(createLabelResponseData);
        }

        List<OrderParcel> orderParcel = orderParcelService.lambdaQuery().eq(OrderParcel::getOrderId, order.getId()).list();
        List<String> trackingNumber = orderParcel.stream().map(OrderParcel::getTrackingNumber).collect(Collectors.toList());

        CreateLabelResponse.Data newCreateLabelResponseData = new CreateLabelResponse.Data();
        newCreateLabelResponseData.setObjectId(objectId);
        newCreateLabelResponseData.setPdfUrl(order.getPdfUrl());
        BigDecimal finalRate = order.getRate();
        newCreateLabelResponseData.setRate(finalRate);
        newCreateLabelResponseData.setStatus(createLabelResponseData.getStatus());
        CreateLabel2Response.FeeDetail newFeeDetail = new CreateLabel2Response.FeeDetail();
        newFeeDetail.setBaseRate(finalRate);
        newCreateLabelResponseData.setFeeDetail(newFeeDetail);

        newCreateLabelResponseData.setCreateTime(createLabelResponseData.getCreateTime());
        newCreateLabelResponseData.setTrackingNumber(trackingNumber);

        String labelUrl = Global.PRINT_LABEL_API + objectId;
        newCreateLabelResponseData.setLabelUrl(Arrays.asList(labelUrl));
        return CommonResult.success(newCreateLabelResponseData);

    }

    @Override
    public CommonResult cancelLabel(String objectId,String orderNo) {
        String strResult =   dqpostlUtil.cancelLabel(objectId,orderNo);
        if (StringUtils.isNotBlank(strResult)) {
            CreateOrderResponse createLabelResponse = JSONUtil.toBean(strResult, CreateOrderResponse.class);
            List<CreateOrderResponse.CreateOrderResponseDetail> result = createLabelResponse.getResult();
            if (CollectionUtil.isNotEmpty(result)) {
                if (result.get(0).getCode() != 300) {
                    return CommonResult.failed(result.get(0).getMsg());
                }
            }
        }
        return CommonResult.success();
    }

    @Override
    public CommonResult tracking(String trackingNumber) {
        String strResult = sjgjwlUtil.tracking(trackingNumber);
        if (StringUtils.isNotBlank(strResult)) {
            CreateOrderResponse createLabelResponse = JSONUtil.toBean(strResult, CreateOrderResponse.class);
            List<CreateOrderResponse.CreateOrderResponseDetail> result = createLabelResponse.getResult();
            if (CollectionUtil.isNotEmpty(result)) {
                if (result.get(0).getCode() != 300) {
                    return CommonResult.failed(result.get(0).getMsg());
                }
            }

        }
        return CommonResult.success();
    }

    @Override
    public CommonResult cancelInsurance(String insuranceId) {

        return CommonResult.success();
    }
}
